package com.sunwayhorizo.health.business.clinic.emr.template;

import static com.sunwayhorizo.health.hl7.vocabulary.EntityIICode.TEMPCLASS;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.emr.template.query.TemplateQueryLocal;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.clinic.emr.template.TemplateClassDTO;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.BAG_EN;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.datatypes.SET_II;
import com.sunwayhorizo.health.hl7.datatypes.common.CSImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.ENImpl;
import com.sunwayhorizo.health.hl7.persistent.RimCoreEntyNames;
import com.sunwayhorizo.health.hl7.persistent.RimCoreRoles;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.Hl7Entity;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityDeterminer;
import com.sunwayhorizo.health.hl7.vocabulary.EntityIICode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNamePartType;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNameUse;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleClass;
import com.sunwayhorizo.health.hl7.vocabulary.RoleCode;

/**
 * @ClassName TempClassManager <br>
 * @PackageName com.sunwayhorizo.health.business.emr.template <br>
 * @Description  <br>
 * @Author jinzw <br>
 * @Date 2011-03-09 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate 2011-06-19<br>
 * @ModifiedBy jinzw<br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */

@Name("TemplateClassManager")
@Stateless
public class TemplateClassManager extends BaseManager implements TemplateClassManagerLocal
{
    private TemplateQueryLocal templateQuery = (TemplateQueryLocal)Component.getInstance("TemplateQuery");
    
    public ResultsDTO newTemplateClass(TemplateClassDTO category) throws Hl7Exception
    {
        if (null == category)
        {
            log.info("新增模板分类失败，模板类型数据为null");
            return this.getResultsDTO("新增模板分类失败，模板类型数据为null", false, null);
        }
        // 初始化基础数据
         String extenID = em.createNativeQuery("select EXTEN_CODE.NEXTVAL from dual").getResultList().get(0).toString();
        Hl7Entity father = null;
        if (!StrUtil.isEmpty(category.getFatherId()))
        {
            //得到父模板分类
            father = baseQuery.findHl7EntityById(Long.valueOf(category.getFatherId()));
        }
        //创建模板分类实体
        CE ce = getDataTypeFactory().newCE(EntityCode.TEMPCLASS.code().stringValue());
        Hl7Entity child = createEntity(ce);
        //给模板分类赋值
        converHl7Entity(category, child);
        //创建模板分类角色
        Role role = null;
        SET_II oraId = getDataTypeFactory().newSET_II(root, "org" + extenID, "true");
        if(null == father)
        {
            role = this.getRoleFactory().newRole(RoleClass.PART, getDataTypeFactory().newCE(RoleCode.TEMPCLASS.code().toString()), 
                child, child, oraId);
        }
        else
        {
            role = this.getRoleFactory() .newRole(RoleClass.PART, getDataTypeFactory().newCE(RoleCode.TEMPCLASS.code().toString()),
                child, father, oraId);
        }
        //创建ControlAct关系
        ControlAct controlAct = newControlAct(ActCode.TEMPCLASS, ParticipationType.SBJ, extenID, role);
        
        em.persist(controlAct);
        log.info("新增模板分类成功"+role.getRoleId());
        return this.getResultsDTO("新增模板分类成功", true, child.getEntityId().toString());
    }


    @SuppressWarnings("rawtypes")
    public ResultsDTO delTemplateClass(List ids) throws Hl7Exception
    {
        if (ListUtil.isEmpty(ids))
        {
            log.info("删除模板分类失败，ids为空");
            return this.getResultsDTO("删除模板分类失败", false, null);
        }
        String classId = (String) ids.get(0); 
        Role roles =  templateQuery.findClassRoleByEntId(classId);
        List<RimCoreRoles> scopers = roles.getPlayerEntities().getScoperRimCoreRolesList();;
        if (scopers.size() > 1)
        {
            log.info("删除模板分类失败，该分类有子分类，不能删除");
            return this.getResultsDTO("该分类有子分类，不能删除", true, null);
        }
        List<Object> docs = templateQuery.findTemplateListByClassTempId(classId);
        if (ListUtil.isNotEmpty(docs))
        {
            log.info("删除模板分类失败，该分类下已有模板文件");
            return this.getResultsDTO("该分类下已有模板文件，不能直接删除", true, null);
        }
        em.remove(roles.getPlayerEntity());
        em.remove(roles);
        log.info("删除模板分类成功,实体id:"+roles.getPlayerEntity().getEntityId()+"角色id："+roles.getRoleId());
        return this.getResultsDTO("删除模板分类成功", true, null);
    }

    public ResultsDTO updateTemplateClass(TemplateClassDTO category) throws Hl7Exception
    {
        if (null == category)
        {
            log.info("更新模板分类失败，category为null");
            return this.getResultsDTO("更新模板分类不成功，分类名称为空 ", true, null);
        }

        Hl7Entity entity = baseQuery.findHl7EntityById(Long.valueOf(category.getId()));
        converHl7Entity(category, entity);
        em.merge(entity);
        log.info("更新模板分类成功：categoryId " + category.getId());
        return this.getResultsDTO("更新模板分类成功", true, null);
    }


    public ResultsDTO findClassTree() throws Hl7Exception
    {
        List<Role> listRoles = templateQuery.findAllTempClassRoleList();
        if (ListUtil.isEmpty(listRoles))
        {
            log.info("获取模板分类角色失败，数据库中没有数据");
            return this.getResultsDTO("模板分类树为空", true, null);
        }
        List<TemplateClassDTO> topCategorys = convertTree(listRoles);

        log.info("获取模板分类树成功");
        return this.getResultsDTO("获取模板分类树成功", true, topCategorys);
    }

    public ResultsDTO findWriteClassTree(String fatherId) throws Hl7Exception
    {
        List<Role> listRoles = templateQuery.findAllTempClassRoleByFatherId(fatherId);
        if (ListUtil.isEmpty(listRoles))
        {
            log.info("获取病历分类角色失败，数据库中没有数据");
            return this.getResultsDTO("该分类下没子类", true, null);
        }
        List<TemplateClassDTO> topCategorys = convertTree(listRoles);

        return this.getResultsDTO("获取病历分类成功", true, topCategorys);
    }

    public String findChildListByFatherId(long fatherId) throws Hl7Exception
    {
        List<Object> roleIds = templateQuery.findChildIdsByFatherId(fatherId);
        if (ListUtil.isNotEmpty(roleIds))
        {
            return "0";
        }
        else
            return "1";
    }

    public List<Long> findTemplateClassIdByFatherId(String fatherId) throws Hl7Exception
    {
        List<Long> list = templateQuery.findTemplateClassIdByFatherId(fatherId);
        if (ListUtil.isNotEmpty(list))
            return list;
        else
            return null;
    }

    public ResultsDTO findWriteClassTreeByFCode(String fatherClassCode) throws Hl7Exception
    {
        Long entityId = templateQuery.findTempClassEntyIdByCode(fatherClassCode);
        return findWriteClassTree(String.valueOf(entityId));
    }


    /**
     * 构建分类树
     * 
     * @param listRoles
     * @return
     * @throws Hl7Exception
     */
    public List<TemplateClassDTO> convertTree(List<Role> listRoles) throws Hl7Exception
    {
        // 抽取RimCoreRoles的数据，将数据注入TemplateCategoryDTO，并设置TemplateCategoryDTO的父子关系
        List<TemplateClassDTO> allCategory = buildUniqueCatgDTO(listRoles);

        // 构建TemplateCategoryDTO树的顶级节点
        List<TemplateClassDTO> topCategorys = new ArrayList<TemplateClassDTO>();
        for (TemplateClassDTO cat : allCategory)
        {
            if (StrUtil.isEmpty(cat.getFatherId()))
            {
                // 如果父节点Id为空，则其为顶级节点
                topCategorys.add(cat);
            }
        }
        // 移除顶级节点，这样可以再构建分类树的时候少循环两次
        for (TemplateClassDTO top : topCategorys)
        {
            allCategory.remove(top);
        }
        // 此处循环主要是为了解决父节点为空的情况下直接拿到所有的子节点
        if (ListUtil.isEmpty(topCategorys))
        {
            return allCategory;
        }
        else
        {
            // 构建分类树
            buildClassTree(topCategorys, allCategory);

            // 垃圾回收
            listRoles = null;
            allCategory = null;
            return topCategorys;
        }

    }


    /**
     * 构建树形结构的dto
     * 
     * @param topCategorys
     *            父节点List
     * @param categoryList
     *            子节点list
     */
    public void buildClassTree(List<TemplateClassDTO> topCategorys, List<TemplateClassDTO> categoryList)
    {
        if (null == categoryList)
            return;
        for (TemplateClassDTO father : topCategorys)
        {
            List<TemplateClassDTO> children = new ArrayList<TemplateClassDTO>();
            for (TemplateClassDTO child : categoryList)
            {
                if (child.getFatherId() == null)
                { // 如果这孩子没爹

                }
                else
                {
                    // 有爹的时候才去判断父子关系
                    if (father.getId().equals(child.getFatherId()))
                    {
                        // 是父子节点关系
                        children.add(child);
                    }

                }
            }
            if (!children.isEmpty())
            {
                // 如果顶级节点有子节点，则需要递归层层构建子节点
                father.setChildren(children);
                buildClassTree(children, categoryList); // 递归构建
            }
        }
    }

    public List<TemplateClassDTO> buildUniqueCatgDTO(List<Role> listRoles) throws Hl7Exception
    {
        if (ListUtil.isEmpty(listRoles))
        {
            // 如果为空，则返回null
            return null;
        }
        List<TemplateClassDTO> all = new ArrayList<TemplateClassDTO>(); // 所有的TemplateCategoryDTO

        // 将所子节点都加进来，设置父节点id
        for (RimCoreRoles role : listRoles)
        {
            Hl7Entity scope = (Hl7Entity)role.getScoperEntities(); // 角色扮演范围,相当于father
            Hl7Entity plyer = (Hl7Entity)role.getPlayerEntities(); // 角色扮演

            TemplateClassDTO father = convertCoreToDto(scope); // 父节点，RimCoreEntities转换为DTO
            TemplateClassDTO child = convertCoreToDto(plyer); // 子节点，RimCoreEntities转换为DTO

            if (father.getId().equals(child.getId()))
            {
                // 如果它既是Player又是Scoper
                child.setFatherId(null);
            }
            else
            {
                child.setFatherId(father.getId()); // 设置父亲节点id
            }
            if (null != role.getRoleId())
                child.setClassRoleId(role.getRoleId().toString()); // 设置模板分类角色id
            child.setNodeFlag(findChildListByFatherId(Long.valueOf(child.getId()))); // 判断节点下面是否有子节点

            all.add(child);
        }
        return all;
    }


    @SuppressWarnings("rawtypes")
    private TemplateClassDTO convertCoreToDto(Hl7Entity core) throws Hl7Exception
    {
        if (null == core)
            return null;
        TemplateClassDTO tcdto = new TemplateClassDTO();
        tcdto.setId(core.getEntityId().toString()); // 节点id

        List<RimCoreEntyNames> coreNames = core.getEntyNamesList();
        if (!ListUtil.isEmpty(coreNames))
        {
            tcdto.setName((coreNames.get(0) != null && !coreNames.get(0).getFormatted().equals("<Null:NI>") ? coreNames.get(0).getFormatted() : "")); 
        }
        II ii = core.getId(EntityIICode.TEMPCLASS);
        tcdto.setClassCode((ii !=null && ii.extension()!=null ? ii.extension().stringValue() : "")); // 分类编码code
        if (null != core.getDesc())
        {
                tcdto.setComments((!core.getDesc().literal().toString().equals("<Null:NullFlavor: NI>")?core.getDesc().literal().toString() : "")); // 模板描述
        }
        if (null != core.getCreatedBy())
            tcdto.setCreatedBy(core.getCreatedBy().toString()); // 创建人
        tcdto.setCreationDate(DateUtil.getFormatTimestamp(core.getCreationDate(), "yyyy-mm-dd hh:mm:ss")); // 创建时间
        if (null != core.getLastUpdatedBy())
            tcdto.setLastUpdateBy(core.getLastUpdatedBy().toString()); // 最后修改人
        tcdto.setLastUpdateDate(DateUtil.getFormatTimestamp(core.getLastUpdateDate(), "yyyy-mm-dd hh:mm:ss")); // 最后修改时间

        return tcdto;
    }

    private Hl7Entity createEntity(CE ce) throws Hl7Exception
    {
        CS cs = EntityDeterminer.INSTANCE;
        Hl7Entity entity = getEntityFactory().newHl7Entity(ce, cs, null);
        return entity;
    }

    private void converHl7Entity(TemplateClassDTO category,Hl7Entity entity) throws Hl7Exception
    {
        if (!StrUtil.isEmpty(category.getName()))
        {
            String name[] = { category.getName() };
            String orgenType[] = { EntityNamePartType.FULL_NAME.code().toString() };
            BAG_EN bagEnName = DataTypeUtil.getBagEN(name, orgenType, EntityNameUse.L.code().toString());
            entity.setName(bagEnName);
        }

        // 分类编码（质量监控代码）
        if (!StrUtil.isEmpty(category.getClassCode()))
        {
            II classCode = DataTypeUtil.getII(root, category.getClassCode(), TEMPCLASS.toString());
            entity.setId(classCode);
        }

        // 模板分类注释
            ED desc = DataTypeUtil.getED(category.getComments());
            entity.setDesc(desc);

        // 创建人
        if (!StrUtil.isEmpty(category.getCreatedBy()))
        {
            entity.setCreatedBy(Long.parseLong(category.getCreatedBy()));
        }
        // 创建时间
        if (StrUtil.isNotEmpty(category.getCreationDate()))
        {
            entity.setCreationDate(DateUtil.getTimestamp(category.getCreationDate()));
        }
        // 最后修改人
        if (!StrUtil.isEmpty(category.getLastUpdateBy()))
        {
            entity.setLastUpdatedBy(Long.parseLong(category.getLastUpdateBy()));
        }
    }



}
